home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
cpp_libs
/
awe2-0_1.lha
/
awe2-0.1
/
Src
/
HardwareContext-m68k.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1990-07-09
|
5KB
|
179 lines
// This may look like C code, but it is really -*- C++ -*-
//
// Copyright (C) 1988 University of Illinois, Urbana, Illinois
// Copyright (C) 1989 University of Colorado, Boulder, Colorado
// Copyright (C) 1990 University of Colorado, Boulder, Colorado
//
// written by Dirk Grunwald (grunwald@foobar.colorado.edu)
//
#include "HardwareContext.h"
#include "CpuMultiplexor.h"
#include "Thread.h"
#include "assert.h"
#include <stream.h>
//
// Many machines have the same (or very similar) stack format.
// The 68K & 32K are examples of such machines.
//
// The const *registers* defines the number of additional longwords
// needed on the stack past the last frame pointer. This value needs
// to jibe with the one in HardwareContext-<arch>.s.
//
const long MagicStackMarker = 0x464f4f20; // this says 'FOO '
//
// checkBytesSaved won't include a6 and a7, so it thinks
// only 10 registers (6 data, 4 address) are saved.
//
static const int expectedBytesSavedInContext
= 4 * 10
+ 4 * HardwareContextFloatQuads;
static int numberOfBytesSavedInContext = 0;
static void computeBytesSaved();
HardwareContext::HardwareContext (int check, unsigned size)
{
checkStackLimits = check;
stackBase = 0;
stackEnd = 0;
stackMax = 0;
stackSize = 0;
stackCheck = 0;
stackMallocAt = 0;
if (size > 0) {
stackSize = size;
stackMallocAt = new void *[ stackSize ];
//
// stackBase should point to the first writeable cell of the
// new stack.
//
stackEnd = stackMallocAt;
stackBase = &stackMallocAt[stackSize-1];
}
else {
//
// Have the main process figure out how many registers
// (actually, Quads) are pushed when we save an entire context.
// Do this by calling magicSwitchTo with itself. This has
// the side-effect of storing fp & sp in the context.
//
magicSwitchTo(this);
numberOfBytesSavedInContext = (long) fp - (long) sp;
assert( numberOfBytesSavedInContext == expectedBytesSavedInContext );
}
}
HardwareContext::reclaimStack()
{
if ( stackMallocAt ) {
if ( check ) {
mprotect(stackMallocAt, pageSizeInBytes, PROT_READ | PROT_WRITE);
}
free(stackMallocAt);
stackMallocAt = 0;
}
}
void
HardwareContext::magicSwitchTo(HardwareContext *to)
{
//
// UNTESTED
//
asm( " " : : :
"d1", "d2", "d3", "d4", "d5", "d6", "d7",
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp",
"fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7");
asm("movl a7,%0" : "=g" (sp));
asm("movl a6,%0" : "=g" (fp));
asm("movl %0,a7" : : "g" (to -> sp));
asm("movl %0,a6" : : "g" (to -> fp));
}
void
HardwareContext::stackOverflow()
{
register unsigned depth = stackBase - getSp();
if (stackMax < depth) {
stackMax = depth;
}
if ( stackMax >= stackSize ) {
cerr << "\nStack overflow\n";
cerr << " getSp() = " << hex(long(getSp()));
cerr << " and stackBase = " << hex(long(stackBase)) << "\n";
cerr << *this << "\n";
cerr << "Current task is \n";
cerr << *(CurrentThread());
cerr << "\n";
cerr.flush();
}
assert( stackMax < stackSize );
assert( *stackCheck == MagicStackMarker );
}
void
HardwareContext::buildReturnFrame(void *returnThis, voidFuncP returnAddress)
{
//
// To build a thread, we return to the first address of startOff,
// which will use the current FP & SP to build a local context,
// and then call the user main.
//
// startOff needs to have a valid frame. The return address for this
// frame is NULL, since we never exit procedure startOff.
//
stackCheck = (long *) stackBase;
HardwareContextQuad **stack = (HardwareContextQuad **) stackBase;
*(stack--) = (HardwareContextQuad *) MagicStackMarker;
*(stack--) = 0; // return address
HardwareContextQuad **startOffFp = stack;
*(stack--) = 0; // frame pointer
//
// Construct the stack frame that will be used in procedure startOff.
// startOff needs to know the value for *this*, which is passed in
// as the first parameter. It also gets the back-link FP for the
// last frame (build above).
//
*(stack--) = (HardwareContextQuad *) returnThis;
HardwareContextQuad **nullFp = stack;
// FP for previous frame
*(stack--) = (HardwareContextQuad *) startOffFp;
//
// Now build the stack frame that is used to return to startOff
//
*(stack--) = (HardwareContextQuad *) returnAddress;
a6 = (HardwareContextQuad) stack;
*(stack) = (HardwareContextQuad *) nullFp;
a7 = (HardwareContextQuad) stack;
}
void
HardwareContext::classPrintOn(ostream& s)
{
s << "[HardwareContext] Stack spans " << hex(long(stackEnd));
s << " to " << hex(long(stackBase));
s << " used is " << (stackMax) << " of " << stackSize << "\n";
s << "[HardwareContext] fp = " << hex(long(a6));
s << " sp = " << hex(long(a7));
long p = *( (long *) a6 );
s << " @fp = " << hex(p) << "\n";
}